#ifndef _CLISTA_H
#define _CLISTA_H

#include "def.h"
#include "disparo.h"
#include "personaje.h"
#include "particulas.h"


/*------------------------------------------------------------------------------
	Dinamic Tempate List implementation  
------------------------------------------------------------------------------*/
template <class tipo> class CLista
{

	typedef struct Nodo
	{
		struct 	Nodo * m_pSiguiente;
		tipo 	m_Info;        
	}NodoLista;

	typedef NodoLista * pNodoLista;

	int Actual;
	char Nombre[255];
	int m_iNumElem;  			
	pNodoLista m_pPrimero;
	pNodoLista m_pUltimo;
	pNodoLista m_pApuntador;
	pNodoLista m_pAnterior;
	
public:

	CLista();              		
	~CLista();
	void Liberar();
	void Insertar(tipo elem);
	tipo Extraer();
	void Borrar();	
	tipo Consultar();
	tipo Siguiente();
	Bool Vacia();	     	
	void ResetearApuntador();
	int  getNumElem();
	void Listar();
	void setNombre(char nombre[255]);
};

/*------------------------------------------------------------------------------
	Constructor
------------------------------------------------------------------------------*/
template <class tipo> CLista<tipo>::CLista()
{
	m_pPrimero=NULL;
	m_pUltimo=NULL;
	
	m_pApuntador=NULL;
	m_pAnterior=NULL;
	
  	m_iNumElem=0;
}

/*------------------------------------------------------------------------------
	Destructor
------------------------------------------------------------------------------*/
template <class tipo> CLista<tipo>::~CLista()
{
	//Liberar(); 
}

/*------------------------------------------------------------------------------
	Frees list memory
------------------------------------------------------------------------------*/
template <class tipo> void CLista<tipo>::Liberar()
{
	ResetearApuntador();
		
	printf("- Elementos lista:%d\n",getNumElem());
	int c=0;
	while(!Vacia())
  	{  	
  		Borrar();
  		c++;
  	}  
  	printf("- Eliminados:%d\n",c);
  	
 	delete m_pPrimero;
  	delete m_pUltimo; 
  	delete m_pApuntador;
  	delete m_pAnterior; 
  	
  	printf("- Lista Liberada\n");  
}

/*------------------------------------------------------------------------------
	Insert a new item in the list
------------------------------------------------------------------------------*/
template <class tipo> void CLista<tipo>::Insertar(tipo elem)
{
	if(!elem)
		return;
		
  	pNodoLista nuevo=new NodoLista;

  	if(!(nuevo))
  	{
		printf("ERROR: Memoria insuficiente.No se pueden crear mas nodos en la Lista\n");
		return;
	}
	
	nuevo->m_Info=elem;
	nuevo->m_pSiguiente=NULL;
	
	if(Vacia())
	{
		m_pPrimero=nuevo;
		m_pApuntador=m_pPrimero;
		m_pAnterior=NULL;
	}
	else
	  	m_pUltimo->m_pSiguiente=nuevo;
	  
	m_pUltimo=nuevo;
	m_iNumElem++;
}


/*------------------------------------------------------------------------------
------------------------------------------------------------------------------*/
template <class tipo>  void CLista<tipo>::setNombre(char nombre[255])
{
	strcpy(Nombre,nombre);
}

/*------------------------------------------------------------------------------
	Shows list members. For Debug purpouse
------------------------------------------------------------------------------*/
template <class tipo>  void CLista<tipo>::Listar()
{
	pNodoLista p,au;
	p=m_pPrimero;
	
	printf("LISTA: %s\n",Nombre);
	while(p)
	{
		printf("[%d->%d]->",p,p->m_pSiguiente);
		au=p;
		p=au->m_pSiguiente;		
	}
	printf("#\n");
	printf("NumElementos:%d\n",m_iNumElem);	
}

/*------------------------------------------------------------------------------
	Erases list element
------------------------------------------------------------------------------*/
template <class tipo>  void CLista<tipo>::Borrar()
{
	if(Vacia() || m_pApuntador==NULL)
		return;

	pNodoLista aux;
	aux=m_pApuntador;
	
	if(!m_pAnterior)
	{
		m_pApuntador=aux->m_pSiguiente;
		m_pPrimero=aux->m_pSiguiente;
	}
	else
	{		
		
		if(m_pApuntador==m_pUltimo)		
		{	
			m_pUltimo=m_pAnterior;
			m_pApuntador=NULL;
		}
		else
			m_pApuntador=aux->m_pSiguiente;

		m_pAnterior->m_pSiguiente=m_pApuntador;
	}	

	m_iNumElem=m_iNumElem-1;
	
	if(Vacia())
	{
		m_pApuntador=NULL;		
		m_pAnterior=NULL;
		m_pPrimero=NULL;
		m_pUltimo=NULL;
	}
		
	if(aux->m_Info)
		aux->m_Info->Liberar();	
		
	if(aux)
		delete aux;
}

/*------------------------------------------------------------------------------
	Returns next item in the list. The actual item is pointed by m_pApuntador
------------------------------------------------------------------------------*/
template <class tipo> tipo CLista<tipo>::Siguiente()
{
	if(Vacia() || m_pApuntador==NULL)
		return NULL;
		
	m_pAnterior=m_pApuntador;
	m_pApuntador=m_pApuntador->m_pSiguiente;	
		
	
	Actual++;
	return (m_pAnterior->m_Info);
}

/*------------------------------------------------------------------------------
	Returns current pointed member
------------------------------------------------------------------------------*/
template <class tipo> tipo CLista<tipo>::Consultar()
{
	if(Vacia() || m_pApuntador==NULL)
		return NULL;		
	
	return (m_pApuntador->m_Info);
}

/*------------------------------------------------------------------------------
	Is List empty?
------------------------------------------------------------------------------*/
template <class tipo> Bool CLista<tipo>::Vacia()
{
	if (m_pPrimero==NULL || m_iNumElem==0)
		return TRUE;
		
	return FALSE;
}

/*------------------------------------------------------------------------------
	Return number of list elements
------------------------------------------------------------------------------*/
template <class tipo> int CLista<tipo>::getNumElem()
{
	return (m_iNumElem);
}

/*------------------------------------------------------------------------------
	Restarts the pointer to a first list member
------------------------------------------------------------------------------*/
template <class tipo>void CLista<tipo>::ResetearApuntador()
{	
	Actual=0;
	m_pApuntador=m_pPrimero;
	m_pAnterior=NULL;	
}

#endif
